/**
 * 
 */
package name.yzhu.httpserver.handle;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;

import name.yzhu.common.lang.LangUtil;
import name.yzhu.httpserver.HttpserverConstant;
import name.yzhu.httpserver.HttpReturnData;
import name.yzhu.httpserver.HttpServerResponseException;

/**
 * @author yhzhu
 *
 */
public class URLHandleToMethod {
	private Method method = null;
	private HandleURLProcess process = null;
	private Class<?>[] paramsTypes = null;
	private HandleMethodeDeclare hmd = null;
	private List<String> extParamName;
	private List<String> extParamValue ;
	private List<String> paramName;
	private Set<String> requiredParam;
	
	
	public URLHandleToMethod(Method method, HandleURLProcess process,
			HandleMethodeDeclare hmd) {
		super();
		this.method = method;
		this.process = process;
		this.hmd = hmd;		
		paramsTypes = method.getParameterTypes();
		
		this.extParamName = hmd.getExtParameterNames();
		this.paramName = hmd.getParameterNames();
		this.requiredParam = hmd.getRequiredParam();
	}
	
	public HttpReturnData invokeFromURLHandle(HttpServletRequest req, HttpServletResponse res)
		throws HttpServerResponseException {
		try{
			int objSize = this.paramsTypes.length;
			Object args[] = new Object[objSize];
			if (hmd.isNative()){
				args[0] = req;
				args[1] = res;
			}
			else {
				int ptIdx = 0;
				if (extParamName != null && extParamName.size() > 0){
					for (int i=0; i<extParamName.size(); i++){
						Class<?> pt = paramsTypes[ptIdx];					
						if (extParamValue!=null && i < extParamValue.size()){
							String value = extParamValue.get(i);
							args[ptIdx++] = LangUtil.converte2PrimaryType(pt, value);
						}
						else {
							args[ptIdx++] = null;
						}
					}
				}
				if (paramName != null && paramName.size() > 0){
					for (String name: paramName){
						Class<?> pt = paramsTypes[ptIdx];
						String value = req.getParameter(name);
						
						if ((Strings.isNullOrEmpty(value) || value.equals("\"\"") ||value.equals("''")) 
								&& this.requiredParam != null && this.requiredParam.contains(name))
							return process.getExceptionData(HandleURLProcess.NOT_ALLOW_NULL, name+" filed can't be empty");
						try{
							Object obj = null;
							if (pt.getSimpleName().equals("List") && value != null){
								obj = Splitter.on(',').splitToList(value);
							}
							else {
								obj = LangUtil.converte2PrimaryType(pt, value);
							}
							args[ptIdx++] = obj;
						}
						catch(IllegalArgumentException e){
							return process.getExceptionData(HandleURLProcess.INVALID_DATA_TYPE, "invalid data type: "+name);
						}
						if (ptIdx == paramsTypes.length)
							break;
					}
				}
				if (hmd.isNativeReqeust())
					args[ptIdx++] = req;
				if (hmd.isNativeResponse())
					args[ptIdx++] = res;
			}
			HttpReturnData  result =  (HttpReturnData) method.invoke(process, args);
			return result;
		}
		catch(Exception e){
			throw new HttpServerResponseException(HttpserverConstant.HTTP_SERVER_INTERNAL_ERROR, e);
		}
	}
	
	public void addExtParamValue(String value){		
		extParamValue.add(value);
	}
	
	public void setExtParamValue(List<String> value){		
		extParamValue = value;
	}
	
	public void cleanExtParamValue(){
		extParamValue.clear();
	}
	
	public HandleURLProcess getProcess(){
		return process;
	}
	
	public HandleMethodeDeclare getHmd(){
		return hmd;
	}

	public Class<?>[] getParamsTypes() {
		return paramsTypes;
	}
}
